/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.control;

import org.zhiqim.kernel.model.interfaces.Openb;
import org.zhiqim.kernel.util.Threads;

/**
 * 线程扩展类，提供一套标准的循环操作的线程抽象类
 * 基类实现如下：
 * 1、线程管理（volatile的isRunning）、线程类thread，以及线程ID
 * 2、不可重写的open/close方法
 * 3、可读写的first/loop方法
 * 
 * 子类操作如下：
 * 1、子类可提供线程组对象或线程名
 * 2、子类可提供open/close操作前后的设置和清理实现
 * 3、子类可提供可选的第一次回调和后续的循环回调实现
 *
 * @version v1.0.0 @author zouzhigang 2018-11-17 新建与整理
 */
public abstract class Threadx implements Runnable, Openb
{
    private volatile boolean isRunning;
    private Thread thread;
    private long threadId;
    
    /*************************************************************************/
    //子类实现的方法
    /*************************************************************************/
    
    /** 子类可选指定线程组 */
    protected ThreadGroup getThreadGroup(){return null;}
    
    /** 子类必须提供线程名 */
    protected abstract String getThreadName();
    
    /** 子类可选在线程开启之前的操作 */
    protected boolean openBefore(){return true;}
    
    /** 子类可选在线程开启之后的操作 */
    protected boolean openAfter(){return true;}
    
    /** 子类可选在线程关闭之前的操作 */
    protected void closeBefore(){}
    
    /** 子类可选在线程关闭之后的操作 */
    protected void closeAfter(){}
    
    /** 子类可选提供的第一次回调方法 */
    protected void first(){};
    
    /** 子类必须提供的循环回调方法 */
    protected abstract void loop();
    
    /*************************************************************************/
    //线程编号&状态
    /*************************************************************************/
    
    /** 线程编号 */
    public final long getThreadId()
    {
        return threadId;
    }
    
    /** 线程是否运行 */
    public final boolean isRunning()
    {
        return isRunning;
    }
    
    /*************************************************************************/
    //开启&关闭&运行
    /*************************************************************************/
    
    @Override /** 开启 */
    public final synchronized boolean open()
    {
        if (isRunning)
            return false;
        
        //1.开启线程之前的操作
        try{if (!openBefore()){return false;}}
        catch(Throwable e){return false;}
        
        //2.开启线程
        thread = new Thread(getThreadGroup(), this, getThreadName());
        thread.start();
        
        //3.阻塞等待线程启动成功
        while (!isRunning){Threads.sleepIgnoreException(3);}
        threadId = thread.getId();
        
        //4.开启线程之后的操作
        try{if (!openAfter()){close();return false;}}
        catch(Throwable e){return false;}
        return true;
    }
    
    @Override /** 关闭 */
    public final synchronized void close()
    {
        if (!isRunning)
            return;
        
        //1.置线程状态为false
        isRunning = false;
        
        //2.关闭线程之前的操作
        try{closeBefore();}catch(Throwable e){}
        
        //3.关闭线程
        threadId = 0;
        if (thread != null)
        {
            try{if (!thread.isInterrupted())thread.interrupt();}catch(Throwable e){}
            thread = null;
        }
        
        //4.关闭线程之后的操作
        try{closeAfter();}catch(Throwable e){}
    }
    
    /** 关闭但不中断当前线程 */
    public final synchronized void closeNotInterrupt()
    {
        if (!isRunning)
            return;
        
        //1.置线程状态为false
        isRunning = false;
        
        //2.关闭线程之前的操作
        try{closeBefore();}catch(Throwable e){}
        
        //3.关闭线程
        threadId = 0;
        if (thread != null)
            thread = null;
        
        //4.关闭线程之后的操作
        try{closeAfter();}catch(Throwable e){}
    }
    
    @Override /** 运行 */
    public final void run()
    {
        //1.线程运行成功
        isRunning = true;
        
        //2.第一次调用
        try{first();}catch(Throwable e){}
        
        //3.循环调用
        while (isRunning)
        {
            try{loop();}catch(Throwable e){}
        }
    }
}
